package sk.stuba.fiit.pki.test;

import java.io.File;
import java.io.FileInputStream;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;

import org.bouncycastle.tsp.TimeStampResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import sk.stuba.fiit.pki.core.CertificateManager;
import sk.stuba.fiit.pki.entity.CertificateEntity;
import sk.stuba.fiit.pki.service.PkiService;

public class GenerateRequiredCertificates {

	private static ApplicationContext context = new FileSystemXmlApplicationContext("./src/test/resources/spring-web-context.xml");
	private static PkiService service = (PkiService) context.getBean("pkiService");

	
	
	public static void main(String[] args) throws Exception{
		clearDatabaze(); 
		initializeDatabaze();
		generateNewTSACertificate();
	}
	
	TimeStampResponse tsr;
	
	public static void initializeDatabaze() throws Exception{
		CertificateManager cm = CertificateManager.getInstance();
		
		//ulozenie root certifikatu
		KeyPair kp_root = cm.generateKeyPair("RSA", 1024);
		X509Certificate root_CA =  cm.generateRootSelfSignedCertificate(kp_root, service.allocateCertSerialNumber());
		X509Certificate[] rootChain = new X509Certificate[1];
		rootChain[0] =  root_CA;
		File file = new File(PkiService.ROOT_CERT_PATH);
		cm.storeCertificateWithPrivateKey(file, kp_root.getPrivate(), rootChain, "password");
		CertificateEntity certificateEntity = new CertificateEntity();
		certificateEntity.convertCertificateToEntity(root_CA);
		certificateEntity.setPk_link(file.getAbsolutePath());
		service.getCertificateService().save(certificateEntity);
		
		//ulozenie certifikatu pre certifikacnu autoritu
		KeyPair kp_ca = cm.generateKeyPair("RSA", 1024);
		X509Certificate cert_CA =  cm.generateCertificateAuthorityCertificate(kp_ca.getPublic(), kp_root.getPrivate(), root_CA,  service.allocateCertSerialNumber());
		rootChain = new X509Certificate[2];
		rootChain[0] = cert_CA;
		rootChain[1] = root_CA;
		file = new File(PkiService.CA_ROOT_PATH);
		cm.storeCertificateWithPrivateKey(file, kp_ca.getPrivate(), rootChain, "password");
		certificateEntity = new CertificateEntity();
		certificateEntity.convertCertificateToEntity(cert_CA);
		certificateEntity.setPk_link(file.getAbsolutePath());
		service.getCertificateService().save(certificateEntity);
				
		//ulozenie koncoveho uzivatelskeho certifikatu
		KeyPair kp_user = cm.generateKeyPair("RSA", 1024);
		X509Certificate certUser =  cm.generateEndEntityCert(kp_user.getPublic(), kp_ca.getPrivate(), cert_CA,  service.allocateCertSerialNumber());
		rootChain = new X509Certificate[3];
		rootChain[0] = certUser;
		rootChain[1] = cert_CA;
		rootChain[2] = root_CA;
		file = new File(PkiService.USER_CERT_PATH);
		cm.storeCertificateWithPrivateKey(file, kp_user.getPrivate(), rootChain, "password");
		certificateEntity = new CertificateEntity();
		certificateEntity.convertCertificateToEntity(certUser);
		certificateEntity.setPk_link(file.getAbsolutePath());
		service.getCertificateService().save(certificateEntity);
		
		
		//ulozenie certifikatu pre casovu peciatku
		KeyPair kp_ts = cm.generateKeyPair("RSA", 1024);
		X509Certificate certTSA = cm.makeCertificate(kp_ts.getPublic(), kp_ca.getPrivate(), cert_CA, false,  service.allocateCertSerialNumber());
		rootChain = new X509Certificate[3];
		rootChain[0] = certTSA;
		rootChain[1] = cert_CA;
		rootChain[2] = root_CA;
		file = new File(PkiService.TSA_PATH);
		cm.storeCertificateWithPrivateKey(file, kp_ts.getPrivate(), rootChain, "password");
		certificateEntity = new CertificateEntity();
		certificateEntity.convertCertificateToEntity(certTSA);
		certificateEntity.setPk_link(file.getAbsolutePath());
		service.getCertificateService().save(certificateEntity);
	}
	
	
	public static void generateNewTSACertificate()  throws Exception{
		CertificateManager cm = CertificateManager.getInstance();
		KeyPair kp_ts = cm.generateKeyPair("RSA", 1024);
		
		X509Certificate rootCA = cm.loadCertificate(PkiService.ROOT_CERT_PATH, "password", PkiService.STORAGE_TYPE);
		X509Certificate certificate = cm.loadCertificate(PkiService.CA_ROOT_PATH, "password", PkiService.STORAGE_TYPE);
		PrivateKey privateKey = cm.loadPrivateKey(PkiService.STORAGE_TYPE,PkiService.CA_ROOT_PATH, "password");
		
		X509Certificate certTSA = cm.makeCertificate(kp_ts.getPublic(), privateKey, certificate, false,  service.allocateCertSerialNumber());
		X509Certificate[] rootChain = new X509Certificate[3];
		rootChain[0] = certTSA;
		rootChain[1] = certificate;
		rootChain[2] = rootCA;
		File file = new File(PkiService.TSA_PATH);
		cm.storeCertificateWithPrivateKey(file, kp_ts.getPrivate(), rootChain, "password");
		CertificateEntity certificateEntity = new CertificateEntity();
		certificateEntity.convertCertificateToEntity(certTSA);
		certificateEntity.setPk_link(file.getAbsolutePath());
		service.getCertificateService().save(certificateEntity);
	}
	
	public static void clearDatabaze(){
		service.cleareAllDatabaze();
	}
}
